using System;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Collections.Generic;

namespace IBNet
{
   /// <summary>
   /// Represents an order for a financial instrument.
   /// </summary>
   [DebuggerDisplay("{OrderType} {ActionSide}, TotalQuantity = {TotalQuantity}, OrderId = {OrderId}")]
   public partial class Order
   {
      /// <summary>
      /// Creates a new Order.
      /// </summary>
      public Order()
      {
         DoAutomaticallyTransmit = true;
         
         // Needed initializations or else error messages upon order submit
         Volatility = decimal.MaxValue;
         DeltaNeutralOrderType = OrderType.Empty;
         DeltaNeutralAuxPrice = decimal.MaxValue;
      }

      #region Properties

      /// <summary>
      /// Gets or sets the order Id for this order.
      /// </summary>
      public int OrderId { get; set; }

      /// <summary>
      /// Gets or sets the OrderFlavor for this order.
      /// </summary>
      public OrderFlavor Flavor { get; set; }

      /// <summary>
      /// Gets or sets the action actionSide (Buy or Sell) for this order.
      /// </summary>
      public ActionSide ActionSide { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether this order is an AllOrNone order.
      /// </summary>
      public bool AllOrNone { get; set; }

      /// <summary>
      /// Gets or sets the stop price for stop-orders and stop-limit orders,
      /// the trailing amount for trailing-stop and trailing-stop-limit orders, 
      /// or the offset amount for relative orders.
      /// </summary>
      public decimal AuxPrice { get; set; }

      /// <summary>
      /// Gets or sets the Id of the client that placed this order.
      /// </summary>
      public int ClientId { get; set; }

      /// <summary>
      /// Gets or sets the limit price for this order.
      /// </summary>
      public decimal LimitPrice { get; set; }

      /// <summary>
      /// Gets or sets the order Id of the parent order of this order. 
      /// Parent Ids are used to child orders automatically when the parent order executes.
      /// </summary>
      public int ParentId { get; set; }

      /// <summary>
      /// Gets or sets the permanent Id for this order. 
      /// Permanent Ids remain the same across TWS sessions.
      /// </summary>
      public int PermId { get; set; }

      /// <summary>
      /// Gets or sets the total quantity for this order.
      /// </summary>
      public int TotalQuantity { get; set; }

      /// <summary>
      /// Gets or sets the order type for this order.
      /// </summary>
      /// <seealso cref="OrderType"/>
      public OrderType OrderType { get; set; }

      /// <summary>
      /// Gets or sets the time in force for this order.
      /// </summary>
      /// <seealso cref="TimeInForce"/>
      public TimeInForce TimeInForce { get; set; }

      /// <summary>
      /// Gets or sets the one-cancels-all group for this order.
      /// </summary>
      public string OneCancelsAllGroup { get; set; }

      /// <summary>
      /// Gets or sets the one-cancels-all type. This field specifies how to handle remaining orders 
      /// in an OCA group when one order or part of an order executes.
      /// </summary>
      /// <seealso cref="OneCancelsAllType"/>
      public OneCancelsAllType OneCancelsAllType { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether to automatically transmit this order 
      /// once it is submitted to TWS.
      /// </summary>
      public bool DoAutomaticallyTransmit { get; set; }

      /// <summary>
      /// Gets or sets the trigger method for this order. TriggerMethod specify how
      /// Stop, Stop-Limit, and Trailing Stop orders are triggered.
      /// </summary>
      /// <seealso cref="TriggerMethod"/>
      public TriggerMethod TriggerMethod { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether this order is 
      /// allowed to be submitted outside of regular trading hours.
      /// </summary>
      public bool AllowSubmitOutsideOfRegularTradingHours { get; set; }

      /// <summary>
      /// Gets or sets the good-after-time for this order. Use format "YYYYMMDD hh:mm:ss (optional time zone)".
      /// </summary>
      public string GoodAfterTime { get; set; }

      /// <summary>
      /// Gets or sets the Good-till-date for this Order. 
      /// Order.TimeInForce must equal TimeInForce.GoodTillDate for this field to work. 
      /// Use format "YYYYMMDD hh:mm:ss (optional time zone)".
      /// </summary>
      public string GoodTillDate { get; set; }

      /// <summary>
      /// Gets or sets the minimum quantity fill requirement for this order.
      /// </summary>
      public int MinimumQuantity { get; set; }

      /// <summary>
      /// Gets or sets the stop price for use with trailing-stop-limit orders.
      /// </summary>
      public decimal StopPriceForTrailStopLimitOrder { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether margin and commission data for this order should
      /// be sent back via the OpenOrderReceived event when this order is submitted, 
      /// with the order not actually being submitted.
      /// </summary>
      public bool IsWhatIfOrder { get; set; }

      #endregion // Properties

      #region Rarely-Used Fields and Institution Fields
      // Change from internal to public to use one of these fields.
      // internal so as to make simpler the Order Intellisense list.

      /// <summary>
      /// Gets or sets the algorithm strategy.
      /// </summary>
      internal string AlgorithmStrategy { get; set; }

      /// <summary>
      /// Gets or sets the list of algorithm parameters.
      /// </summary>
      internal IList<TagValue> AlgorithmParameters { get; set; }

      /// <summary>
      /// Gets or sets the auction strategy. For BOX exchange only.
      /// </summary>
      /// <seealso cref="AuctionStrategy"/>
      internal AuctionStrategy AuctionStrategy { get; set; }

      /// <summary>
      /// Gets or sets the basis points for an EFP order.
      /// </summary>
      internal decimal BasisPoints { get; set; }

      /// <summary>
      /// Gets or sets the basis points type for an EFP order.
      /// </summary>
      internal int BasisPointsType { get; set; }

      /// <summary>
      /// Gets or sets the delta neutral aux price for a VOL order. 
      /// Set this field if the value in DeltaNeutralOrderType
      /// is an order type that requires an Aux price, such as a REL order. 
      /// </summary>
      internal decimal DeltaNeutralAuxPrice { get; set; }

      /// <summary>
      /// Gets or sets the delta neutral order type for a VOL order. 
      /// Enter an order type to instruct TWS to submit a
      /// delta neutral trade on full or partial execution of the VOL order.
      /// For a no-hedge delta order to be sent, specify NONE.
      /// </summary>
      internal OrderType DeltaNeutralOrderType { get; set; }

      /// <summary>
      /// Gets or sets the reference price type used for dynamic management of VOL orders. 
      /// Set to 1 = Average of National Best Bid or Ask, 
      /// or set to 2 = National Best Bid when buying a call or selling a put; 
      /// and National Best Ask when selling a call or buying a put.
      /// </summary>
      internal int ReferencePriceType { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether this order is an ISE Block order.
      /// </summary>
      internal bool BlockOrder { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether this order is a sweep-to-fill order.
      /// </summary>
      internal bool SweepToFill { get; set; }

      /// <summary>
      /// Gets or sets the publicly-disclosed order size used when placing Iceberg orders.
      /// </summary>
      internal int DisplaySize { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether this order will be visible when 
      /// viewing the market depth when this order is routed to the ISLAND exchange.
      /// </summary>
      internal bool IsHiddenOnIsland { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether this order is allowed to overrride
      /// TWS price percentage constraints set to reject orders that deviate too far from the NBBO.
      /// </summary>
      internal bool CanOverridePercentageConstraints { get; set; }

      /// <summary>
      /// Gets or sets the agent description associated with this order. 
      /// Rule80A requires you to identify what type of trader you.
      /// </summary>
      /// <seealso cref="AgentDescription"/>
      internal AgentDescription Rule80A { get; set; }

      /// <summary>
      /// Gets or sets the percent offset for relative orders.
      /// </summary>
      internal decimal PercentOffset { get; set; }

      /// <summary>
      /// Gets or sets the financial advisor group this order will be allocated to.
      /// </summary>
      internal string FinancialAdvisorGroup { get; set; }

      /// <summary>
      /// Gets or sets the financial advisor profile this order will be allocated to.
      /// </summary>
      internal string FinancialAdvisorProfile { get; set; }

      /// <summary>
      /// Gets or sets the financial advisor allocation method this order will be allocated with.
      /// </summary>
      internal FinancialAdvisorAllocationMethod FinancialAdvisorAllocationMethod { get; set; }

      /// <summary>
      /// Gets or sets the financial advisor percentage associated with this order.
      /// </summary>
      internal string FinancialAdvisorPercentage { get; set; }

      /// <summary>
      /// Gets or sets the amount off the limit price allowed for discretionary orders.
      /// </summary>
      internal decimal DiscretionaryAmmount { get; set; }

      /// <summary>
      /// Gets or sets the stock reference price used for VOL orders.
      /// The reference price is used for VOL orders to compute the limit price sent 
      /// to an exchange (whether or not Continuous Update is selected), 
      /// and for price range monitoring.
      /// </summary>      
      internal decimal StockReferencePrice { get; set; }

      /// <summary>
      /// Gets or sets the stock delta used for BOX orders.
      /// </summary>
      internal decimal Delta { get; set; }

      /// <summary>
      /// Gets or sets or sets the lower value for the acceptable underlying stock price range.
      /// Use this for price-improvement option orders on BOX and VOL orders with dynamic management.
      /// </summary>
      internal decimal StockRangeLower { get; set; }

      /// <summary>
      /// Gets or sets the the upper value for the acceptable underlying stock price range.
      /// Use this for price-improvement option orders on BOX and VOL orders with dynamic management.
      /// </summary>
      internal decimal StockRangeUpper { get; set; }

      /// <summary>
      /// Gets or sets the volatility for VOL orders. Volatility is expressed as a percentage.
      /// This field is populated with what TWS's Options Analytics computes.
      /// </summary>
      internal decimal Volatility { get; set; }

      /// <summary>
      /// Gets or sets how the volatility is calculated: Daily or Annual.
      /// </summary>
      /// <seealso cref="VolatilityType"/>
      internal VolatilityType VolatilityType { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether to use continuous update for 
      /// dynamic management of volatility orders. Unknown what value to specify to do what.
      /// </summary>
      /// <remarks>Determines whether TWS is
      /// supposed to update the order price as the underlying moves. If selected,
      /// the limit price sent to an exchange is modified by TWS if the computed price
      /// of the option changes enough to warrant doing so.  This is very helpful in
      /// keeping the limit price sent to the exchange up to date as the underlying price changes.</remarks>
      internal int ContinuousUpdate { get; set; }

      /// <summary>
      /// Gets or sets the number of buckets X to split this order into.
      /// </summary>
      internal int ScaleInitialLevelSize { get; set; }

      /// <summary>
      /// Gets or sets the size X to split the order into such that each bucket is of size X.
      /// </summary>
      internal int ScaleSubLevelSize { get; set; }

      /// <summary>
      /// Gets or sets the price increment per bucket.
      /// </summary>
      internal decimal ScalePriceIncrement { get; set; }

      /// <summary>
      /// Gets or sets the starting price used for BOX orders.
      /// </summary>
      internal decimal StartingPrice { get; set; }

      /// <summary>
      /// Gets or sets the short sale slot for this order.
      /// </summary>
      internal ShortSaleSlot ShortSaleSlot { get; set; }

      /// <summary>
      /// Gets or sets the designated location. Set only when shortSaleSlot value = 2.
      /// </summary>
      internal string DesignatedLocation { get; set; }

      /// <summary>
      /// Gets or sets the maximum Smart order distance from the NBBO.
      /// </summary>
      internal decimal NbboPriceCap { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether to use only electronic quotes.
      /// </summary>
      internal bool UseOnlyElectronicQuotes { get; set; }

      /// <summary>
      /// Gets or sets a value indicating whether to use only firm quotes.
      /// </summary>
      internal bool UseOnlyFirmQuotes { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal string ClearingAccount { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal string ClearingIntent { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal string SettlingFirm { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal string Account { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal string OpenClose { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal OrderOrigin Origin { get; set; }

      /// <summary>
      /// Institution field.
      /// </summary>
      internal string OrderReference { get; set; }

      #endregion // Rarely-Used Fields and Institution Fields
   }
}